﻿using System;
using System.ComponentModel;

using DevExpress.Xpo;
using DevExpress.Xpo.Metadata;
using DevExpress.Data.Filtering;

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.Base;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation;
using DevExpress.ExpressApp.Security;
using DevExpress.ExpressApp.Security.Strategy;

namespace WaTP.Module.BusinessObjects
{
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("Name")]
    public class Categories : BaseObject
    {
        public Categories(Session session)
            : base(session)
        {
            // This constructor is used when an object is loaded from a persistent storage.
            // Do not place any code here or place it only when the IsLoading property is false:
            // if (!IsLoading){
            //    It is now OK to place your initialization code here.
            // }
            // or as an alternative, move your initialization code into the AfterConstruction method.
        }
        private string name;//Tên phân loại.
        [RuleRequiredField(DefaultContexts.Save)]
        public string Name {
            get { return name; }
            set { SetPropertyValue("Name", ref name, value); }
        }
        private string code;//Mã phân loại.
        public string Code {
            get { return code; }
            set { SetPropertyValue("Code", ref code, value); }
        }

        [Association("Product-Categories")]
        public XPCollection<Product> Products {
            get { return GetCollection<Product>("Products"); }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            // Place here your initialization code.
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("ProductCode")]
    public class Product : BaseObject {
        public Product(Session session)
            : base(session) { }
        private string productCode;//Mã sản phẩm.
        //[RuleRequiredField(DefaultContexts.Save)]
        public string ProductCode {
            get {
                //if (Grade == null || Standard == null || Coating == null || Supplier != null || Size != null || Material != null)
                //    productCode = null;
                //else
                if (Grade != null && Supplier != null && Size != null)
                {
                    if (Standard != null && Coating != null)
                        productCode = Grade.Code + Standard.Code + ModifySize(Size) + Coating.Code
                        + Supplier.SupplierCode;// bulong, thanh ren, ecu thép, vòng đệm thép.
                    else {
                        if (Standard != null && Coating == null)
                            productCode = Grade.Code + Standard.Code + ModifySize(Size) + Supplier.SupplierCode;//Ecu Inox.
                        else
                            if (Coating != null)
                            {
                                productCode = Grade.Code + ModifySize(Size) + Coating.Code + Supplier.SupplierCode;//Khác
                            }
                            else
                                if(MarkSteel != null && Standard != null && Coating == null){
                                    productCode = Grade.Code + MarkSteel.Code + Standard.Code + ModifySize(Size) + Supplier.SupplierCode;// Vòng đệm Inox.
                                }
                                else
                                    productCode = Grade.Code + ModifySize(Size) + Supplier.SupplierCode;//Viton
                    }
                }
                return productCode; }
            //set { SetPropertyValue("ProductCode", ref productCode, value); }
        }
        private string vietnameseName;//Tên sản phẩm tiếng Việt.
        [RuleRequiredField(DefaultContexts.Save)]
        public string VietnameseName {
            get { return vietnameseName; }
            set { SetPropertyValue("VietnameseName", ref vietnameseName, value); }
        }
       
        private Standard standard;//Tiêu chuẩn
        public Standard Standard {
            get { return standard; }
            set { SetPropertyValue("Standard", ref standard, value); }
        }

        //private Material material;// Vật liệu
        //public Material Material {
        //    get { return material; }
        //    set { SetPropertyValue("Material", ref material, value); }
        //}

        private Coating coating;// Xử lý lớp mạ
        public Coating Coating {
            get { return coating; }
            set { SetPropertyValue("Coating", ref coating, value); }
        }

        private Grade grade;// Cấp bền.
        public Grade Grade {
            get { return grade; }
            set { SetPropertyValue("Grade", ref grade, value); }
        }

        private MarkSteel markSteel;//Mác thép.
        public MarkSteel MarkSteel {
            get { return markSteel; }
            set { SetPropertyValue("MarkSteel", ref markSteel, value); }
        }
        private Categories categories;//Phân loại
        [Association("Product-Categories")]
        [RuleRequiredField(DefaultContexts.Save)]
        public Categories Categories {
            get { return categories; }
            set { SetPropertyValue("Categories", ref categories, value); }
        }

        private string size;//Kích thước.
        public string Size {
            get { return size; }
            set { SetPropertyValue("Size", ref size, value); }
        }
        private float weight;//Đơn trọng.
        public float Weight {
            get { return weight; }
            set { SetPropertyValue("Weight", ref weight, value); }
        }
        private Unit unit;
        public Unit Unit {
            get { return unit; }
            set { SetPropertyValue("Unit", ref unit, value); }
        }

        private Supplier supplier;
        [Association("Supplier-Products")]
        public Supplier Supplier {
            get { return supplier; }
            set { SetPropertyValue("Supplier", ref supplier, value); }
        }
        public int? TotalInventory { //Tổng tồn kho.
            get { return InventoryQuantity1 + InventoryQuantity2 + InventoryQuantity3; }
        }

        private int? minStock = null;
        public int? MinStock {
            get { return minStock; }
            set { SetPropertyValue("MinStock", ref minStock, value); }
        }

        private StockStatus stockStatus;
        public StockStatus StockStatus {
            get {
                if (TotalInventory > MinStock)
                {
                    stockStatus = StockStatus.Available;
                }
                else {
                    if (TotalInventory <= MinStock && TotalInventory > 0)
                    {
                        stockStatus = StockStatus.Warning;
                    }
                    else {
                        stockStatus = StockStatus.OutOfStock;
                    }
                }
                return stockStatus; }
            set { SetPropertyValue("StockStatus", ref stockStatus, value); }
        }
        #region Warehouse Total 1 Information
        [Persistent("ImportQuantity1")]
        private int? importQuantity1 = null;// Số lượng đã nhập kho tại Tổng kho 1.
        [PersistentAlias("importQuantity1")]
        public int? ImportQuantity1 {
            get {
                if (!IsLoading && !IsSaving && importQuantity1 == null)
                    UpdateImportTotal1(false);
                return importQuantity1; }
        }
        [Persistent("ExportQuantity1")]
        private int? exportQuantity1 = null;//Số lượng đã xuất kho tại Tổng kho 1.
        [PersistentAlias("exportQuantity1")]
        public int? ExportQuantity1 {
            get {
                if (!IsLoading && !IsSaving && exportQuantity1 == null)
                    UpdateExportTotal1(false);
                return exportQuantity1; }
        }
        //private int inventoryQuantity1;//Số lượng tồn kho tại Tổng kho 1.
        public int? InventoryQuantity1 {
            get { return ImportQuantity1 + ExportQuantity1; }
        }
        private string locationTotal1;//Vị trí tại Tổng kho 1.
        public string LocationTotal1 {
            get { return locationTotal1; }
            set { SetPropertyValue("LocationTotal1", ref locationTotal1, value); }
        }
        //Hàm tính tổng nhập của tổng kho 1.
        public void UpdateImportTotal1(bool forceChangeEvents)
        {
            int? oldImportQuantity1 = importQuantity1;
            int tempImport = 0;
            foreach(WareHouseTotal1 detail in Total1){
                if(detail.OrderCategory.OrderName == "Import" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempImport += detail.Quantity;
            }
            importQuantity1 = tempImport;
            if (forceChangeEvents)
                OnChanged("ImportQuantity1", oldImportQuantity1, importQuantity1);
        }
        //Hàm tính tổng xuất của tổng kho 1.
        public void UpdateExportTotal1(bool forceChangeEvents) {
            int? oldExportQuantity1 = exportQuantity1;
            int tempExport = 0;
            foreach(WareHouseTotal1 detail in Total1){
                //if (detail.Order == WarehouseOrder.ExportOrder)
                if(detail.OrderCategory.OrderName == "Export" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempExport += detail.Quantity;
            }
            exportQuantity1 = tempExport;
            if (forceChangeEvents)
                OnChanged("ExportQuantity1", oldExportQuantity1, exportQuantity1);
        }
        #endregion
        #region Warehouse Total 2 Information
        [Persistent("ImportQuantity2")]
        private int? importQuantity2 = null;
        [PersistentAlias("importQuantity2")]
        public int? ImportQuantity2 {
            get {
                if (!IsLoading && !IsSaving && importQuantity2 == null)
                    UpdateImportTotal2(false);
                return importQuantity2; }
        }

        [Persistent("ExportQuantity2")]
        private int? exportQuantity2 = null;
        [PersistentAlias("exportQuantity2")]
        public int? ExportQuantity2 {
            get {
                if (!IsLoading && !IsSaving && exportQuantity2 == null)
                    UpdateExportTotal2(false);
                return exportQuantity2; }
        }

        //private int? inventoryQuantity2;
        public int? InventoryQuantity2 {
            get { return ImportQuantity2 + ExportQuantity2 ; }
        }
        private string locationTotal2;
        public string LocationTotal2 {
            get { return locationTotal2; }
            set { SetPropertyValue("LocationTotal2", ref locationTotal2, value); }
        }
        public void UpdateImportTotal2(bool forceChangeEvents) {
            int? oldImportQuantity2 = importQuantity2;
            int tempImport = 0;
            foreach (WareHouseTotal2 detail in Total2)
            {
                //if (detail.Order == WarehouseOrder.ImportOrder)
                if(detail.OrderCategory.OrderName == "Import" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempImport += detail.Quantity;
            }
            importQuantity2 = tempImport;
            if (forceChangeEvents)
                OnChanged("ImportQuantity2", oldImportQuantity2, importQuantity2);
        }
        public void UpdateExportTotal2(bool forceChangeEvents) {
            int? oldExportQuantity2 = exportQuantity2;
            int tempExport = 0;
            foreach (WareHouseTotal2 detail in Total2)
            {
                //if (detail.Order == WarehouseOrder.ExportOrder)
                if(detail.OrderCategory.OrderName == "Export" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempExport += detail.Quantity;
            }
            exportQuantity2 = tempExport;
            if (forceChangeEvents)
                OnChanged("ExportQuantity2", oldExportQuantity2, exportQuantity2);
        }
        #endregion
        #region Warehouse Total 3 Information
        [Persistent("ImportQuantity3")]
        private int? importQuantity3 = null;
        [PersistentAlias("importQuantity3")]
        public int? ImportQuantity3 {
            get {
                if (!IsLoading && !IsSaving && importQuantity3 == null)
                    UpdateImportTotal3(false);
                return importQuantity3; }
        }
        [Persistent("ExportQuantity3")]
        private int? exportQuantity3 = null;
        [PersistentAlias("exportQuantity3")]
        public int? ExportQuantity3 {
            get {
                if (!IsLoading && !IsSaving && exportQuantity3 == null)
                    UpdateExportTotal3(false);
                return exportQuantity3; }
        }
        //private int inventoryQuantity3;
        public int? InventoryQuantity3 {
            get { return ImportQuantity3 + ExportQuantity3; }
        }
        private string locationTotal3;
        public string LocationTotal3 {
            get { return locationTotal3; }
            set { SetPropertyValue("LocationTotal3", ref locationTotal3, value); }
        }
        //
        public void UpdateImportTotal3(bool forceChangeEvents)
        {
            int? oldImportQuantity3 = importQuantity3;
            int tempImport = 0;
            foreach (WareHouseTotal3 detail in Total3)
            {
                //if (detail.Order == WarehouseOrder.ImportOrder)
                if(detail.OrderCategory.OrderName == "Import" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempImport += detail.Quantity;
            }
            importQuantity3 = tempImport;
            if (forceChangeEvents)
                OnChanged("ImportQuantity3", oldImportQuantity3, importQuantity3);
        }
        public void UpdateExportTotal3(bool forceChangeEvents)
        {
            int? oldExportQuantity3 = exportQuantity3;
            int tempExport = 0;
            foreach (WareHouseTotal3 detail in Total3)
            {
                //if (detail.Order == WarehouseOrder.ExportOrder)
                if(detail.OrderCategory.OrderName == "Export" && detail.Status != WarehouseOrderStatus.Cancel)
                    tempExport += detail.Quantity;
            }
            exportQuantity3 = tempExport;
            if (forceChangeEvents)
                OnChanged("ExportQuantity3", oldExportQuantity3, exportQuantity3);
        }
        #endregion

        private void Reset() {
            importQuantity1 = null;
            exportQuantity1 = null;
            importQuantity2 = null;
            exportQuantity2 = null;
            importQuantity3 = null;
            exportQuantity3 = null;
        }
        //Xử lý Size
        private string ModifySize(string inputString) {
            string temp = null;
            for (int i = 0; i < inputString.Length; i++)
            {
                if ((inputString[i].ToString() == "0") || (inputString[i].ToString() == "1")
                    || (inputString[i].ToString() == "2") || (inputString[i].ToString() == "3")
                    || (inputString[i].ToString() == "4") || (inputString[i].ToString() == "5")
                    || (inputString[i].ToString() == "6") || (inputString[i].ToString() == "7")
                    || (inputString[i].ToString() == "8") || (inputString[i].ToString() == "9"))
                {
                    temp += inputString[i].ToString();
                }
            }
                return temp;
        }
        protected override void OnLoaded()
        {
            Reset();
            base.OnLoaded();
        }
        [Association("Products-WarehouseTotal1")]
        public XPCollection<WareHouseTotal1> Total1 {
            get { return GetCollection<WareHouseTotal1>("Total1");}
        }
        [Association("Products-WarehouseTotal2")]
        public XPCollection<WareHouseTotal2> Total2 {
            get { return GetCollection<WareHouseTotal2>("Total2");}
        }
        [Association("Products-WarehouseTotal3")]
        public XPCollection<WareHouseTotal3> Total3 {
            get { return GetCollection<WareHouseTotal3>("Total3");}
        }
        [Association("Product-CostHistories"), Aggregated]
        public XPCollection<CostHistory> CostHistories {
            get { return GetCollection<CostHistory>("CostHistories"); }
        }
        [Association("Product-PriceHistories")]
        public XPCollection<PriceHistory> PriceHistories {
            get { return GetCollection<PriceHistory>("PriceHistories"); }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            stockStatus = StockStatus.Available;
            unit = Unit.Piece;
        }
    }
    [DefaultClassOptions]
    public class Standard : LibraryBase {
        public Standard(Session session)
            : base(session) { }
    }
    //[DefaultClassOptions]
    //public class Material : LibraryBase {
    //    public Material(Session session)
    //        : base(session) { }
    //}
    [DefaultClassOptions]
    public class Grade : LibraryBase {
        public Grade(Session session)
            : base(session) { }
    }
    [DefaultClassOptions]
    public class Coating : LibraryBase {
        public Coating(Session session)
            : base(session) { }
    }
    [DefaultClassOptions]
    public class MarkSteel : LibraryBase {
        public MarkSteel(Session session)
            : base(session) { }
    }
    [System.ComponentModel.DefaultProperty("Code")]
    public class LibraryBase : BaseObject {
        public LibraryBase(Session session)
            : base(session) { }
        private string code;
        [RuleRequiredField(DefaultContexts.Save)]
        public string Code {
            get { return code; }
            set { SetPropertyValue("Code", ref code, value); }
        }
        private string vietnameseDescription;
        [RuleRequiredField(DefaultContexts.Save)]
        public string VietnameseDescription {
            get { return vietnameseDescription; }
            set { SetPropertyValue("VietNameseDescription", ref vietnameseDescription, value); }
        }
        private string englishDescription;
        public string EnglisDescription {
            get { return englishDescription; }
            set { SetPropertyValue("EnglishDescription", ref englishDescription, value); }
        }
    }

    public class WarehouseBase : BaseObject {
        public WarehouseBase(Session session)
            : base(session) { }
        
        private Contract contract;//Hợp đồng, Lô...
        public Contract Contract {
            get { return contract; }
            set { SetPropertyValue("Contract", ref contract, value); }
        }
        private OrderCategory orderCategory;
        public OrderCategory OrderCategory
        {
            get { return orderCategory; }
            set { SetPropertyValue("OrderCategory", ref orderCategory, value); }
        }
        private OrderType orderType;
        [DataSourceProperty("OrderCategory.Types")]
        public OrderType OrderType {
            get { return orderType; }
            set { SetPropertyValue("OrderType", ref orderType, value); }
        }
        [Persistent("CreateOn"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime _CreateOn = DateTime.Now;
        [PersistentAlias("_CreateOn")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime CreateOn
        {
            get { return _CreateOn; }
        }
        internal virtual void UpdateCreatedOn()
        {
            UpdateCreatedOn(DateTime.Now);
        }
        internal virtual void UpdateCreatedOn(DateTime date)
        {
            _CreateOn = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "Contract")
            {
                UpdateCreatedOn();
            }
        }

        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        private WarehouseOrderStatus status;//Trạng thái Lệnh xuất/ nhập.
        public WarehouseOrderStatus Status {
            get { return status; }
            set { SetPropertyValue("Status", ref status, value); }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            status = WarehouseOrderStatus.InProgress;
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("OrderCode")]
    public class WareHouseTotal1 : WarehouseBase {
        public WareHouseTotal1(Session session)
            : base(session) { }
        private Categories categories;//Phân loại hàng hóa giúp cho việc lọc sản phẩm khi lựa chọn.
        public Categories Categories
        {
            get { return categories; }
            set { SetPropertyValue("Categories", ref categories, value); }
        }
        private int quantity;//Số lượng xuất/nhập.
        public int Quantity
        {
            get
            {
                //if (OrderCategory.OrderName == "Export")
                //    quantity = -quantity;
                return quantity; }
            set { 
                SetPropertyValue("Quantity", ref quantity, value); 
                if(!IsLoading && !IsSaving && Product != null){
                    Product.UpdateImportTotal1(true);
                    Product.UpdateExportTotal1(true);                   
                }
            }
        }
        private Product product;//Hàng hóa.
        [Association("Products-WarehouseTotal1")]
        [DataSourceProperty("Categories.Products")]
        public Product Product
        {
            get { return product; }
            set { SetPropertyValue("Product", ref product, value); }
        }

        private TransferOrder transferOrder;
        [Association("TransferOrder-WarehouseTotal1")]
        public TransferOrder TransferOrder {
            get { return transferOrder; }
            set { SetPropertyValue("TransferOrder", ref transferOrder, value); }
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("OrderCode")]
    public class WareHouseTotal2 : WarehouseBase {
        public WareHouseTotal2(Session session)
            : base(session) { }
        private Categories categories;
        public Categories Categories {
            get { return categories; }
            set { SetPropertyValue("Categories", ref categories, value); }
        }

        private int quantity;
        public int Quantity {
            get {
                //if (OrderCategory.OrderName == "Export")
                //    quantity = -quantity;
                return quantity; }
            set { 
                SetPropertyValue("Quantity", ref quantity, value);
                if (!IsLoading && !IsSaving && Product != null)
                {
                    Product.UpdateImportTotal2(true);
                    Product.UpdateExportTotal2(true);
                }
            }
        }
        private Product product;
        [Association("Products-WarehouseTotal2")]
        [DataSourceProperty("Categories.Products")]
        public Product Product {
            get { return product; }
            set { SetPropertyValue("Product", ref product, value); }
        }

        private TransferOrder transferOrder;
        [Association("TransferOrder-WarehouseTotal2")]
        public TransferOrder TransferOrder {
            get { return transferOrder; }
            set { SetPropertyValue("TransferOrder", ref transferOrder, value); }
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("OrderCode")]
    public class WareHouseTotal3 : WarehouseBase {
        public WareHouseTotal3(Session session)
            : base(session) { }
        private Categories categories;
        public Categories Categories {
            get { return categories; }
            set { SetPropertyValue("Categories", ref categories, value); }
        }
        private int quantity;
        public int Quantity {
            get {
                //if (OrderCategory.OrderName == "Export")
                //    quantity = -quantity;
                return quantity; }
            set { 
                SetPropertyValue("Quantity", ref quantity, value);
                if (!IsLoading && !IsSaving && Product != null)
                {
                    Product.UpdateImportTotal3(true);
                    Product.UpdateExportTotal3(true);
                }
            }
        }
        private Product product;
        [Association("Products-WarehouseTotal3")]
        [DataSourceProperty("Categories.Products")]
        public Product Product {
            get { return product; }
            set { SetPropertyValue("Product", ref product, value); }
        }
        private TransferOrder transferOrder;
        [Association("TransferOrder-WarehouseTotal3")]
        public TransferOrder TransferOrder {
            get { return transferOrder; }
            set { SetPropertyValue("TransferOrder", ref transferOrder, value); }
        }
    }
    [DefaultClassOptions]
    public class Supplier : CompanyBase {
        public Supplier(Session session)
            : base(session) { }
        private string supplierCode;//Mã nhà cung cấp.
        public string SupplierCode {
            get { return supplierCode; }
            set { SetPropertyValue("SupplierCode", ref supplierCode, value); }
        }
        private Country country;
        public Country Country {
            get { return country; }
            set { SetPropertyValue("Country", ref country, value); }
        }
        [Association("Supplier-Products")]
        public XPCollection<Product> Products {
            get { return GetCollection<Product>("Products"); }
        }
        [Association("Supplier-Contracts")]
        public XPCollection<Contract> Contracts {
            get { return GetCollection<Contract>("Contracts");}
        }
    }
    [DefaultClassOptions]
    [System.ComponentModel.DefaultProperty("ContractNo")]
    public class Contract : BaseObject {
        public Contract(Session session) :
            base(session) { }
        private string contractNo;
        public string ContractNo {
            get { return contractNo; }
            set { SetPropertyValue("ContractNo", ref contractNo, value); }
        }
        private string contractName;
        public string ContractName {
            get { return contractName; }
            set { SetPropertyValue("ContractName", ref contractName, value); }
        }
        private Supplier supplier;
        [Association("Supplier-Contracts")]
        public Supplier Supplier {
            get { return supplier; }
            set { SetPropertyValue("Supplier", ref supplier, value); }
        }
        private DateTime contractDateTime;//Ngày hợp đồng.
        public DateTime ContractDateTime {
            get { return contractDateTime; }
            set { SetPropertyValue("ContractDateTime", ref contractDateTime, value); }
        }
        [Association("Contract-QualityTest")]
        public XPCollection<QualityTest> QualTest {
            get { return GetCollection<QualityTest>("QualTest");}
        }
        [Association("Contract-Formalities")]
        public XPCollection<CustomsFormality> Formalities{
            get { return GetCollection<CustomsFormality>("Formalities");}
        }
    }
    [DefaultClassOptions]
    public class QualityTest : BaseObject {
        public QualityTest(Session session)
            : base(session) { }
        private string subject;
        public string Subject {
            get { return subject; }
            set { SetPropertyValue("Subject", ref subject, value); }
        }
        private QualityTestMethod method;
        public QualityTestMethod Method {
            get { return method; }
            set { SetPropertyValue("Method", ref method, value); }
        }
        private DateTime startDateTime;
        public DateTime StartDateTime {
            get { return startDateTime; }
            set { SetPropertyValue("StartDateTime", ref startDateTime, value); }
        }
        private DateTime endDateTime;
        public DateTime EndDateTime {
            get { return endDateTime; }
            set { SetPropertyValue("EndDateTime", ref endDateTime, value); }
        }
        private string description;
        [Size(1024)]
        public string Description {
            get { return description; }
            set { SetPropertyValue("Description", ref description, value); }
        }
        private QualityTestStatus status;
        public QualityTestStatus Status {
            get { return status; }
            set { SetPropertyValue("Status", ref status, value); }
        }
        //User
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        private Contract contract;
        [Association("Contract-QualityTest")]
        public Contract Contract {
            get { return contract; }
            set { SetPropertyValue("Contract", ref contract, value); }
        }
        [Association("Quality-Activities"), Aggregated]
        public XPCollection<Activity> Activities {
            get { return GetCollection<Activity>("Activities");}
        }
        [Association("Quality-Documents"), Aggregated]
        public XPCollection<Document> Documents {
            get { return GetCollection<Document>("Documents");}
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
            status = QualityTestStatus.InProgress;
        }
    }

    public enum QualityTestStatus {
        [ImageName("State_Task_InProgress")]
        InProgress,
        [ImageName("State_Task_Completed")]
        Completed
    }
    public enum QualityTestMethod { 
        Purchase,//Mua hàng.
        Sales//Bán hàng
    }
    //[DefaultClassOptions]
    public class Activity : BaseObject {
        public Activity(Session session)
            : base(session) { }
        private string subject;//mô tả vắn tắt công việc.
        public string Subject {
            get { return subject; }
            set { SetPropertyValue("Subject", ref subject, value); }
        }
        private string description;// Mô tả chi tiết công việc.
        [Size(1024)]
        public string Description {
            get { return description; }
            set { SetPropertyValue("Description", ref description, value); }
        }
        //Ngày khởi tạo
        [Persistent("StartDate"), ValueConverter(typeof(UtcDateTimeConverter))]
        protected DateTime startDate = DateTime.Now;
        [PersistentAlias("startDate")]
        [ModelDefault("EditMask", "G")]
        [ModelDefault("DisplayFormat", "{0:G}")]
        public DateTime StartDate {
            get { return startDate; }
            
        }
        internal virtual void UpdateStartDate()
        {
            UpdateStartDate(DateTime.Now);
        }
        internal virtual void UpdateStartDate(DateTime date)
        {
            startDate = date;
            Save();
        }
        protected override void OnChanged(string propertyName, object oldValue, object newValue)
        {
            base.OnChanged(propertyName, oldValue, newValue);
            if (propertyName == "Subject") {
                UpdateStartDate();
            }
        }

        private DateTime endDate;
        public DateTime EndDate {
            get { return endDate; }
            set { SetPropertyValue("EndDate", ref endDate, value); }
        }
        private ActivityStatus status;
        public ActivityStatus Status {
            get { return status; }
            set { SetPropertyValue("Status", ref status, value); }
        }

        //User
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User {
            get { return user; }
            internal set { user = value; }
        }

        private TransferOrder transferOrder;
        [Association("TransferOrder-Activities")]
        public TransferOrder TransferOrder {
            get { return transferOrder; }
            set { SetPropertyValue("TransferOrder", ref transferOrder, value); }
        }

        private QualityTest qualityTest;
        [Association("Quality-Activities")]
        public QualityTest QualityTest {
            get { return qualityTest; }
            set { SetPropertyValue("QualityTest", ref qualityTest, value); }
        }

        private CustomsFormality customsFormality;
        [Association("Formality-Activities")]       
        public CustomsFormality CustomsFormality {
            get { return customsFormality; }
            set { SetPropertyValue("CustomsFormality", ref customsFormality, value); }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            Status = ActivityStatus.InProgress;
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
    }

    public enum ActivityStatus { 
        [ImageName("State_Task_InProgress")]
        InProgress,
        [ImageName("State_Task_Completed")]
        Completed,
        [ImageName("State_Validation_Invalid")]
        Canceled
    }

    public enum StockStatus { 
        [ImageName("State_Validation_Valid")]
        Available,//Còn hàng
        [ImageName("State_Validation_Invalid")]
        OutOfStock,// Hết hàng.
        [ImageName("BO_Attention")]
        Warning// Cảnh báo.

    }
    public enum WarehouseOrderStatus {
        [ImageName("State_Task_InProgress")]
        InProgress,//Đang xử lý.
        [ImageName("State_Validation_Valid")]
        Approve,//Xác nhận.
        [ImageName("State_Validation_Invalid")]
        Cancel//Hủy
        
    }
    public enum Unit { 
        Piece, //chiếc, cái
        Bar,// Thanh
        Plate//Tấm
    }
    [DefaultClassOptions]
    public class Country : BaseObject { 
        public Country(Session session):
            base(session){}
        private string countryName;
        [RuleRequiredField(DefaultContexts.Save)]
        public string CountryName {
            get { return countryName; }
            set { SetPropertyValue("CountryName", ref countryName, value); }
        }
    }

    //Cost Price History
    public class CostPriceBase : BaseObject{
        public CostPriceBase(Session session) : base(session){}
        private Contract contract;
        public Contract Contract {
            get { return contract; }
            set { SetPropertyValue("Contract", ref contract, value); }
        }
        private DateTime date;
        public DateTime Date {
            get { return date; }
            set { SetPropertyValue("Date", ref date, value); }
        }
        private double unitPriceCost;
        public double UnitPriceCost {
            get { return unitPriceCost; }
            set { SetPropertyValue("UnitPriceCost", ref unitPriceCost, value); }
        }
        //User.
        [Persistent("User")]
        private SecuritySystemUser user;
        [PersistentAlias("user")]
        public SecuritySystemUser User
        {
            get { return user; }
            internal set { user = value; }
        }
        public override void AfterConstruction()
        {
            base.AfterConstruction();
            user = Session.GetObjectByKey<SecuritySystemUser>(SecuritySystem.CurrentUserId);
        }
    }

    public class CostHistory : CostPriceBase {
        public CostHistory(Session session) : base(session) { }

        private Product product;
        [Association("Product-CostHistories")]
        public Product Product {
            get { return product; }
            set { SetPropertyValue("Product", ref product, value); }
        }
    }

    public class PriceHistory : CostPriceBase {
        public PriceHistory(Session session) : base(session) { }
        private Department department;
        public Department Department {
            get { return department; }
            set { SetPropertyValue("Department", ref department, value); }
        }

        private Product product;
        [Association("Product-PriceHistories")]
        public Product Product {
            get { return product; }
            set { SetPropertyValue("Product", ref product, value); }
        }
    }
}
